#include <SDL/SDL.h>
#include <iostream>

#include "timesystem.h"
#include "game.h"
#include "config.h"

#include "defaultsetting.h"

using namespace std;

volatile unsigned long TimeSystem::masterTick=0;

TimeSystem::TimeSystem():m_tickTime(0),m_actualFrameskip(0),m_maxFrameskip(0),
  m_totalFrameskip(0),m_maxFPS(0),m_actualGraphicTick(0),m_actualLogicTick(0),
  m_oldTick(0)
{
}

TimeSystem::~TimeSystem()
{
	SDL_RemoveTimer(timerID);
}

bool TimeSystem::load()
{
  Config& s=Game::self().getSetting();
  m_maxFPS=s["time"].readEntry("MaxFPS",TIME_MAX_FPS);
  m_tickTime=s["time"].readEntry("ticktime",TIME_TICK_TIME);
  m_maxFrameskip=s["time"].readEntry("max_frameskip",TIME_MAX_FRAMESKIP);

	if(!(timerID=SDL_AddTimer(m_tickTime,tickCounter,NULL)))
		return -1;

	return 0;
}

Uint32 TimeSystem::tickCounter(Uint32 interval,void *parameter)
{
	TimeSystem::masterTick++;
	return interval;
}

bool TimeSystem::isLogicTick()
{
  // Si el actual tick logico es menor que el tick maestro entonces
  // vamos retrasados y hay que hacer uno logico.
	if(m_actualLogicTick<=masterTick)
	{
		m_actualLogicTick++;
    // Si ha pasado un segundo.
    if(masterTick-m_oldTick>=ticksPerSecond())
    {
      cout<<"fps: "<<m_actualGraphicTick<<" fs: "<<m_totalFrameskip<<endl;
      m_actualGraphicTick=0;
      m_totalFrameskip=0;
      m_oldTick=masterTick;
    }
		return true;
	}
	else
		return false;

}

bool TimeSystem::isGraphicTick()
{
	// Si el juego no va retrasado o hemos pasado de pintar demasiadas
  // veces pintamos.
	if(m_actualLogicTick>masterTick || m_actualFrameskip>m_maxFrameskip)
	{
		//Si hay un gran desfase entre lo grafico y la logica
		//normalizamos la situacion
		if(m_actualFrameskip>m_maxFrameskip)
			m_actualLogicTick=masterTick;

		//Si llevo mas frames que los que deberia llevar en el tick actual
		//paro para no sobrecargar la CPU
		if(m_actualGraphicTick>=((float)m_maxFPS/ticksPerSecond())*(m_actualLogicTick-m_oldTick))
		{
			SDL_Delay(10);
			return false;
		}
		else
		{
			m_actualGraphicTick++;
			m_actualFrameskip=0;
			return true;
		}
	}
	else
	{
		m_actualFrameskip++;
		m_totalFrameskip++;
		return false;
	}
}

inline unsigned TimeSystem::ticksPerSecond()const
{
  return 1000/masterTick;
}

inline float TimeSystem::getTimeTick()const
{
  return (float)masterTick/1000;
}
